home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / pccp019.zip / XMODEMR.C < prev    next >
Text File  |  1992-05-04  |  7KB  |  370 lines

  1. /*    Copyright (C) 1992 Peter Edward Cann, all rights reserved.
  2.  *    MicroSoft QuickC: >qcl term.c graphics.lib
  3.  */
  4.  
  5. #include<stdio.h>
  6. #include<bios.h>
  7. #include<dos.h>
  8. #include<fcntl.h>
  9. #include<sys\types.h>
  10. #include<sys\stat.h>
  11. #include<signal.h>
  12.  
  13. #define DLLSBREG 0
  14. #define DLMSBREG 1
  15. #define INTCTLREG 1
  16. #define INTIDREG 2
  17. #define LCTLREG 3
  18. #define MCTLREG 4
  19. #define STATREG 5
  20. #define MSTATREG 6
  21.  
  22. #define CTSMASK 0x10
  23. #define TXMTMASK 0x20
  24. #define RXRDYMASK 0x01
  25.  
  26. #define INTACK 0x20
  27.  
  28. #define DB7 0x02
  29. #define DB8 0x03
  30. #define STOP2 0x04
  31. #define PARITYEN 0x08
  32. #define PARITYEVEN 0x10
  33. #define DLAB 0x80
  34.  
  35. #define INTBASE1 0x20
  36. #define INTMASK1 0x21
  37. #define INTBASE2 0xa0
  38. #define INTMASK2 0xa1
  39.  
  40. #define TBUFSIZ 256
  41.  
  42. #define NAK 21
  43. #define ACK 6
  44. #define SOH 1
  45. #define EOT 4
  46. #define CAN 24
  47.  
  48. int index, basereg;
  49. unsigned char buf[TBUFSIZ];
  50. unsigned char diffintmask, irqnum;
  51. void (interrupt far *oldvect)();
  52.  
  53. void interrupt far inthndl(_es, _ds, _di, _si, _bp, _sp,
  54.               _bx, _dx, _cx, _ax, _ip, _cs, _flags)
  55.     unsigned _es, _ds, _di, _si, _bp, _sp;
  56.     unsigned _bx, _dx, _cx, _ax, _ip, _cs, _flags;
  57.     {
  58.     if(inp(basereg+STATREG)&RXRDYMASK)
  59.         {
  60.         buf[index++]=inp(basereg)&0xff;
  61.         index=index%TBUFSIZ;
  62.         }
  63.     outp(INTBASE1, INTACK);
  64.     outp(INTBASE2, INTACK);
  65.     }
  66.  
  67. sendchar(c)
  68.     unsigned char c;
  69.     {
  70.     while(!((inp(basereg+STATREG)&TXMTMASK)&&(inp(basereg+MSTATREG)&CTSMASK)));
  71.     outp(basereg, c);
  72.     }
  73.  
  74. int follow;
  75.  
  76. int rcharto(ticks)
  77.     int ticks;
  78.     {
  79.     long tstamp, tstamp1, dayofticksp;
  80.     int c;
  81.     _bios_timeofday(_TIME_GETCLOCK, &tstamp);
  82.     dayofticksp=0;
  83.     while(1)
  84.         {
  85.         if(_bios_timeofday(_TIME_GETCLOCK, &tstamp1))
  86.             dayofticksp+=20*60*60*24;
  87.         if(tstamp1+dayofticksp-tstamp>ticks)
  88.             return(-1); /* NOTE: This is an INT!!! */
  89.         if(follow!=index)
  90.             {
  91.             c=buf[follow++];
  92.             follow=follow%TBUFSIZ;
  93.             return(c);
  94.             }
  95.         }
  96.     }
  97.  
  98.  
  99. unsigned char block[128];
  100.  
  101. rblock()
  102.     {
  103.     int i, blockn, invblockn, rchecksum, checksum;
  104.     checksum=0;
  105.     if((blockn=rcharto(20))==-1)
  106.         return(-1);
  107.     printf("Block %d: ", blockn);
  108.     if((invblockn=rcharto(20))==-1)
  109.         return(-1);
  110.     for(i=0;i<128;++i)
  111.         {
  112.         if((block[i]=rcharto(20))==-1)
  113.             return(-1);
  114.         checksum+=block[i];
  115.         checksum&=0xff;
  116.         }
  117.     if((rchecksum=rcharto(20))==-1)
  118.         return(-1);
  119.     if(((invblockn^0xff)&0xff)!=blockn)
  120.         {
  121.         printf("Bad complement block number.\n");
  122.         return(-1);
  123.         }
  124.     if(checksum!=rchecksum)
  125.         {
  126.         printf("Checksum mismatch. Here=%02x There=%02x.\n", checksum, rchecksum);
  127.         return(-1);
  128.         }
  129.     return(blockn);
  130.     }
  131.  
  132. unsigned intnum;
  133. unsigned char oldintmask;
  134.  
  135. cleanup()
  136.     {
  137.     if(intnum==10)
  138.         outp(INTMASK2, oldintmask);
  139.     else
  140.         outp(INTMASK1, oldintmask);
  141.     outp(basereg+INTCTLREG, 0x00);
  142.     outp(basereg+MCTLREG, 0x03);
  143.     _dos_setvect(intnum, oldvect);
  144.     }
  145.  
  146. quit()
  147.     {
  148.     cleanup();
  149.     exit(99);
  150.     }
  151.  
  152. main(argc, argv)
  153.     int argc;
  154.     char **argv;
  155.     {
  156.     int i, j, outfd, ok, c;
  157.     long nbytes;
  158.     unsigned char newintmask, lctl, dlmsb, dllsb, blocknum;
  159.     unsigned speed;
  160.     int comnum;
  161.     char stopbits;
  162.     index=follow=0;
  163.     lctl=0;
  164.     printf("Copyright (C) 1992 Peter Edward Cann, all rights reserved.\n");
  165.     printf("xmodem checksum receive of %s.\n", argv[4]);
  166.     if(argc!=5)
  167.         {
  168.         printf("USAGE: xmodemr <comnum> <bps> <stopbits> <file pathname>\n");
  169.         exit(1);
  170.         }
  171.     if((outfd=open(argv[4], O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, S_IWRITE))==-1)
  172.         {
  173.         printf("Error opening file %s.\n", argv[4]);
  174.         exit(2);
  175.         }
  176.     comnum=atoi(argv[1])-1;
  177.     newintmask=0;
  178.     switch(comnum)
  179.         {
  180.         case 0:
  181.             irqnum=4;
  182.             diffintmask=0xff&~0x10;
  183.             basereg=0x3f8;
  184.             break;
  185.         case 1:
  186.             irqnum=3;
  187.             diffintmask=0xff&~0x08;
  188.             basereg=0x2f8;
  189.             break;
  190.         case 2:
  191.             irqnum=4;
  192.             diffintmask=0xff&~0x10;
  193.             basereg=0x3e8;
  194.             break;
  195.         case 3:
  196.             irqnum=3;
  197.             diffintmask=0xff&~0x08;
  198.             basereg=0x2e8;
  199.             break;
  200.         case 4:
  201.             irqnum=2;
  202.             diffintmask=0xff&~0x02;
  203.             basereg=0x3e8;
  204.             break;
  205.         case 5:
  206.             irqnum=2;
  207.             diffintmask=0xff&~0x02;
  208.             basereg=0x2e8;
  209.             break;
  210.         case 6:
  211.             irqnum=5;
  212.             diffintmask=0xff&~0x20;
  213.             basereg=0x3e8;
  214.             break;
  215.         case 7:
  216.             irqnum=5;
  217.             diffintmask=0xff&~0x20;
  218.             basereg=0x2e8;
  219.             break;
  220.         default:
  221.             printf("Bad port choice.\n");
  222.             exit(4);
  223.         }
  224.     intnum=irqnum+8;
  225.     speed=atoi(argv[2]);
  226.     switch(speed)
  227.         {
  228.         case 300:
  229.             dlmsb=0;
  230.             dllsb=0xc0;
  231.             break;
  232.         case 1200:
  233.             dlmsb=0;
  234.             dllsb=0x60;
  235.             break;
  236.         case 2400:
  237.             dlmsb=0;
  238.             dllsb=0x30;
  239.             break;
  240.         case 9600:
  241.             dlmsb=0;
  242.             dllsb=0x0c;
  243.             break;
  244.         case 19200:
  245.             dlmsb=0;
  246.             dllsb=0x06;
  247.             break;
  248.         case 38400:
  249.             dlmsb=0;
  250.             dllsb=0x03;
  251.             break;
  252.         case 57600:
  253.             dlmsb=0;
  254.             dllsb=0x02;
  255.             break;
  256.         default:
  257.             printf("Bad speed.\n");
  258.             exit(5);
  259.         }
  260.     lctl|=DB8;
  261.     stopbits=argv[3][0];
  262.     switch(stopbits)
  263.         {
  264.         case '1':
  265.             break;
  266.         case '2':
  267.             lctl|=STOP2;
  268.             break;
  269.         default:
  270.             printf("Bad stop bits.\n");
  271.             exit(9);
  272.         }
  273.     signal(SIGINT, quit);
  274.     outp(basereg+LCTLREG, DLAB);
  275.     outp(basereg+DLLSBREG, dllsb);
  276.     outp(basereg+DLMSBREG, dlmsb);
  277.     outp(basereg+LCTLREG, lctl);
  278.     oldvect=_dos_getvect(intnum);
  279.     _dos_setvect(intnum, inthndl);
  280.     outp(basereg+INTCTLREG, 0x00);
  281.     outp(basereg+MCTLREG, 0x0b);
  282.     oldintmask=(intnum==10)?inp(INTMASK2):inp(INTMASK1);
  283.     newintmask=diffintmask;
  284.     newintmask&=oldintmask;
  285.     if(intnum==10)
  286.         outp(INTMASK2, newintmask);
  287.     else
  288.         outp(INTMASK1, newintmask);
  289.     outp(INTBASE1, INTACK);
  290.     outp(INTBASE2, INTACK);
  291.     outp(basereg+INTCTLREG, 0x01);
  292.     outp(INTBASE1, INTACK);
  293.     outp(INTBASE2, INTACK);
  294.     ok=nbytes=0;
  295.     for(i=0;i<10;++i)
  296.         {
  297.         sendchar(NAK);
  298.         c=rcharto(200);
  299.         if(c==SOH)
  300.             {
  301.             ok=1;
  302.             break;
  303.             }
  304.         }
  305.     if(!ok)
  306.         {
  307.         printf("No SOH after 10 10-second-spaced NAKs.\n");
  308.         cleanup();
  309.         exit(10);
  310.         }
  311.     blocknum=1;
  312.     for(i=0;i<10;++i)
  313.         {
  314.         printf("\nSeeking block %d: ", blocknum);
  315.         if((c=rblock())==blocknum)
  316.             {
  317.             i=0;
  318.             if(write(outfd, block, 128)!=128)
  319.                 {
  320.                 printf("Write error.\n");
  321.                 cleanup();
  322.                 exit(13);
  323.                 }
  324.             nbytes+=128;
  325.             printf("Successful. Bytes so far: %ld", nbytes);
  326.             blocknum=(blocknum+1)&0xff;
  327.             sendchar(ACK);
  328.             }
  329.         else
  330.             if(c==-1)
  331.                 {
  332.                 while(rcharto(20)!=-1);
  333.                 sendchar(NAK);
  334.                 }
  335.             else if(c<blocknum)
  336.                 sendchar(ACK);
  337.             else
  338.                 {
  339.                 printf("\nSender skipped a block; cancelling transfer.\n");
  340.                 for(j=0;j<10;++j)
  341.                     sendchar(CAN);
  342.                 cleanup();
  343.                 exit(14);
  344.                 }
  345.         do
  346.             c=rcharto(200);
  347.         while((c!=EOT)&&(c!=SOH)&&(c!=CAN)&&(c!=-1));
  348.         if(c==EOT)
  349.             {
  350.             sendchar(ACK);
  351.             printf("\nTransfer successful.\n");
  352.             close(outfd);
  353.             cleanup();
  354.             exit(0);
  355.             }
  356.         if(c!=SOH)
  357.             {
  358.             if(c==-1)
  359.                 printf("Timeout waiting for SOH or EOT.\n");
  360.             else
  361.                 printf("Spurrious character hex %02x; SOH or EOT expected.\n", c);
  362.             cleanup();
  363.             exit(11);
  364.             }
  365.         }
  366.     printf("Retry limit exceeded.\n");
  367.     cleanup();
  368.     exit(12);
  369.     }
  370.